# -*- coding: utf-8 -*-
import datetime

from odoo import models, fields, api, _
from odoo.exceptions import UserError


class SBAccountCheckingWizardLine(models.TransientModel):
    _name = 'sb.account.checking.wizard.line'
    _description = 'Wizard Line'

    wizard_id = fields.Many2one('sb.account.checking.wizard', string='Wizard')
    invoice_id = fields.Many2one('account.move', string='Invoice', required=True)
    currency_id = fields.Many2one(related='invoice_id.currency_id', store=True, readonly=True)
    invoice_total = fields.Monetary(related='invoice_id.amount_total', string='Invoice Total', readonly=True, currency_field='currency_id')
    residual_amount = fields.Monetary(related='invoice_id.amount_residual', string='Unpaid Amount', readonly=True)
    payment_amount = fields.Monetary(string='Payment Amount', required=True, currency_field='currency_id')
    hold_open = fields.Boolean(string='Hold Open', default=False,
                               help="If checked and amount is less than total, invoice remains open (partial state).")


class SBAccountCheckingWizard(models.TransientModel):
    _name = 'sb.account.checking.wizard'
    _description = 'Reconciliation Wizard'

    checking_id = fields.Many2one('sb.account.checking', string='Checking')
    line_ids = fields.One2many('sb.account.checking.wizard.line', 'wizard_id', string='Invoice Lines')
    # check_type = fields.Selection([
    #     ('full', 'Settle Fully'),
    #     ('partial', 'Leave Balance'),
    # ], string='Reconciliation Type', default='full')
    writeoff_account_id = fields.Many2one('account.account', string='Write-Off Account', required=True,
                                          domain="[('reconcile', '=', False), ('deprecated', '=', False)]")
    currency_id = fields.Many2one('res.currency', string='Currency', related='checking_id.currency_id')

    @api.model
    def default_get(self, fields_list):
        res = super().default_get(fields_list)
        loss = self.env['account.account'].search([('name', 'ilike', 'loss')], limit=1)
        if loss:
            res['writeoff_account_id'] = loss.id
        checking = self.env['sb.account.checking'].browse(self.env.context.get('default_checking_id', False))
        lines = []
        for inv in checking.invoice_ids:
            lines.append((0, 0, {
                'invoice_id': inv.id,
                'payment_amount': inv.amount_residual,
            }))
        res['line_ids'] = lines
        return res

    def action_confirm_payment(self):
        reconciled = self.env['account.move.line']
        for line in self.line_ids:
            amt = line.payment_amount
            if not amt or amt <= 0:
                continue
            inv = line.invoice_id
            rec_lines = inv.line_ids.filtered(lambda l: l.account_id.account_type == 'asset_receivable' and not l.reconciled)
            if not rec_lines:
                continue
            # 创建虚拟付款
            payment = self.env['account.payment'].create({
                'payment_type': 'inbound',
                'partner_type': 'customer',
                'partner_id': inv.partner_id.id,
                'amount': amt,
                'currency_id': inv.currency_id.id,
                'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id,
                'journal_id': self.env['account.journal'].search([('type', '=', 'bank')], limit=1).id,
                'date': fields.Date.context_today(self),
                'destination_account_id': rec_lines[0].account_id.id,
                'ref': f"Checking {self.checking_id.name or ''} - {inv.name}",
            })
            payment.action_post()

            # 执行核销
            pay_lines = payment.move_id.line_ids.filtered(lambda l: l.account_id == rec_lines[0].account_id and not l.reconciled)
            to_rec = rec_lines + pay_lines
            to_rec.reconcile()
            reconciled |= to_rec

            # 判断是否需要生成 write-off
            if not line.hold_open:
                residual = inv.amount_residual
                if residual and abs(residual) > inv.company_id.currency_id.rounding:
                    journal = self.env['account.journal'].search([('type', '=', 'general')], limit=1)
                    move = self.env['account.move'].create({
                        'move_type': 'entry',
                        'journal_id': journal.id,
                        'date': fields.Date.context_today(self),
                        'line_ids': [
                            (0, 0, {
                                'account_id': rec_lines[0].account_id.id,
                                'partner_id': inv.partner_id.id,
                                'name': 'Write-Off',
                                'debit': residual if residual > 0 else 0.0,
                                'credit': -residual if residual < 0 else 0.0,
                            }),
                            (0, 0, {
                                'account_id': self.writeoff_account_id.id,
                                'partner_id': inv.partner_id.id,
                                'name': 'Write-Off',
                                'credit': residual if residual > 0 else 0.0,
                                'debit': -residual if residual < 0 else 0.0,
                            }),
                        ]
                    })
                    move.action_post()
                    writeoff_lines = move.line_ids.filtered(lambda l: l.account_id == rec_lines[0].account_id and not l.reconciled)
                    writeoff_lines.reconcile()
                    reconciled |= writeoff_lines

            # 更新发票状态
            ship_lines = self.checking_id.ship_instructions_lines.filtered(lambda l: l.name == inv.name)
            if line.hold_open and line.payment_amount < inv.amount_total:
                new_state = 'partial'
            else:
                new_state = 'done'
            ship_lines.write({'sb_check_state': new_state})

        # 标记整体结算完成
        total_received = sum(self.line_ids.mapped('payment_amount'))
        self.checking_id.write({
            'state': 'done',
            'finish_date': datetime.datetime.now(),
            'name': self.env['ir.sequence'].next_by_code('sb.account.checking'),
            'received_amount': total_received,
        })
